#!/usr/bin/perl

#################################################
# to extract unique tokens from packet-db report
#################################################

use strict;
use warnings;
use Time::Local;

if (@ARGV < 1 || @ARGV > 2) {
	goto LOC_USAGE;
}

my $column;
my $pattern;
my $slice = 0;
my @interval = (0,0);
my $nextarg = shift @ARGV;

if ($nextarg =~ /^\d+$/) {
	$column = scalar $nextarg;
	if ($column > 15 || $column < 1 ) {
		print "column index out of range\n";
		exit;
	}

	$pattern = shift @ARGV;

} elsif ($nextarg =~ /^\d\d\.\d\d\.\d\d\d\d\s+\d\d:\d\d:\d\d\s*--\s*\d\d\.\d\d\.\d\d\d\d\s+\d\d:\d\d:\d\d$/) {
	my @interstr = split('--', $nextarg);
	$interstr[0] =~ s/\s+$//;
	$interstr[1] =~ s/^\s+//;
	@interval = db_time_to_epoch(@interstr);
} else {
	if ($nextarg =~ /^[S|s]\d+$/) {
		$slice = scalar substr $nextarg, 1;
	} elsif ($nextarg =~ /^[M|m]\d+$/) {
		$slice = 60 * scalar substr $nextarg, 1;
	} elsif ($nextarg =~ /^[H|h]\d+$/) {
		$slice = 60 * 60 * scalar substr $nextarg, 1;
	}

	if (!$slice) {
LOC_USAGE:
		print "Usage: $0 <column [pattern]|slice|interval>\n";
		print "  will read from stdin\n";
		print "  column number is 1-based, can be followed by pattern\n";
		print "  slice as S<seconds> or M<minutes> or H<hours>\n";
		print "  interval as \"DD.MM.YYYY HH:MM:SS -- DD.MM.YYYY HH:MM:SS\"\n";
		exit;
	}
}

my %EntryMap = ();

while (<>) {
	if (/^\d\d\.\d\d\.\d\d\d\d \d{1,2}:\d\d(:\d\d)?\|/) {
		my @entry = split /\|/;
		if ($slice > 0 || $interval[1] > 0) {
			my @einter = db_time_to_epoch(@entry);
			if ($slice) {
				my $key = int ($einter[0]/$slice) * $slice;
				if (not exists $EntryMap{$key}) {
					$EntryMap{$key} = [@einter,1];
				} else {
					if (@{$EntryMap{$key}}[0] > $einter[0]) {
						@{$EntryMap{$key}}[0] = $einter[0];
					}
					if (@{$EntryMap{$key}}[1] < $einter[1]) {
						@{$EntryMap{$key}}[1] = $einter[1];
					}
					@{$EntryMap{$key}}[2]++;
				}
			} else {
				if (not (($einter[0] < $interval[0] && $einter[1] < $interval[0])
						|| ($einter[0] > $interval[1] && $einter[1] > $interval[1]))) {
					print $_;
				}
			}
		} else {
			my $key = $entry[$column-1];
			$key =~ s/^\s+//;
			$key =~ s/\s+$//;
			if (defined $pattern) {
				if ( $key =~ /$pattern/ ) {
					print $_;
				}
			} elsif (not exists $EntryMap{$key}){
				$EntryMap{$key} = 1;
			} else {
				$EntryMap{$key}++;
			}
		}
	}
}

if ($slice > 0) {
	for (values %EntryMap) {
		print scalar localtime @$_[0], " -- ", scalar localtime @$_[1], " : ", @$_[2], "\n";
	}
} elsif (!$interval[1]) {
	while (my($key,$value) = each %EntryMap) {
		print $key, " : ", $value, "\n";
	}
} 

sub db_time_to_epoch {
	my @tbeg = split / /, $_[0];
	my @tend = split / /, $_[1];
	my @tbdat = split /\./, $tbeg[0];
	my @tbtim = split /\:/, $tbeg[1];
	my @tedat = split /\./, $tend[0];
	my @tetim = split /\:/, $tend[1];
	
	return (timelocal($tbtim[2],$tbtim[1],$tbtim[0],$tbdat[0],$tbdat[1]-1,$tbdat[2]),
			timelocal($tetim[2],$tetim[1],$tetim[0],$tedat[0],$tedat[1]-1,$tedat[2]));
}

